#pragma once

#include <mcp/config.h>
#include <mcp/forward.h>
#include <mcp/types.h>
#include <mcp/error.h>

#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include <optional>
#include <regex>

namespace mcp {
namespace server {

/// @brief Resource registration information
struct ResourceRegistration {
    std::string uri_template;
    std::string name;
    std::optional<std::string> description;
    std::string mime_type = "text/plain";
    std::function<Result<types::ResourceContent>(const std::string&, Context<>&)> handler;

    ResourceRegistration() = default;
    ResourceRegistration(std::string uri_template,
                        std::string name,
                        std::optional<std::string> description,
                        std::string mime_type,
                        std::function<Result<types::ResourceContent>(const std::string&, Context<>&)> handler)
        : uri_template(std::move(uri_template))
        , name(std::move(name))
        , description(std::move(description))
        , mime_type(std::move(mime_type))
        , handler(std::move(handler)) {}
};

/// @brief Manager for MCP resources
class ResourceManager {
public:
    ResourceManager();
    ~ResourceManager();

    /// @brief Register a new resource
    /// @param registration Resource registration information
    /// @return true if registration succeeded, false if resource already exists
    bool register_resource(ResourceRegistration registration);

    /// @brief Unregister a resource
    /// @param uri_template Resource URI template to unregister
    /// @return true if unregistration succeeded, false if resource not found
    bool unregister_resource(const std::string& uri_template);

    /// @brief Check if a resource exists
    /// @param uri_template Resource URI template
    /// @return true if resource exists, false otherwise
    bool has_resource(const std::string& uri_template) const;

    /// @brief Get all registered resources
    /// @return List of resource definitions
    std::vector<types::Resource> list_resources() const;

    /// @brief Get all resource templates
    /// @return List of resource template definitions
    std::vector<types::ResourceTemplate> list_resource_templates() const;

    /// @brief Get a specific resource definition
    /// @param uri_template Resource URI template
    /// @return Resource definition if found, std::nullopt otherwise
    std::optional<types::Resource> get_resource(const std::string& uri_template) const;

    /// @brief Read a resource by URI
    /// @param uri Resource URI to read
    /// @param context MCP context for the operation
    /// @return Resource content or error
    Result<types::ResourceContent> read_resource(const std::string& uri,
                                                 Context<>& context);

    /// @brief Find matching resource template for a URI
    /// @param uri Resource URI to match
    /// @return Matching resource template and extracted arguments, or std::nullopt
    std::optional<std::pair<ResourceRegistration, std::unordered_map<std::string, std::string>>>
    find_matching_template(const std::string& uri) const;

    /// @brief Extract arguments from URI based on template
    /// @param uri_template Resource URI template
    /// @param uri Actual resource URI
    /// @return Extracted arguments or error
    static std::expected<std::unordered_map<std::string, std::string>, std::string>
    extract_arguments(const std::string& uri_template, const std::string& uri);

    /// @brief Validate resource URI against template
    /// @param uri_template Resource URI template
    /// @param uri Resource URI to validate
    /// @return true if URI matches template, false otherwise
    static bool validate_uri(const std::string& uri_template, const std::string& uri);

    /// @brief Clear all registered resources
    void clear();

private:
    struct Impl;
    std::unique_ptr<Impl> impl_;
};

} // namespace server
} // namespace mcp